package ar.com.ford.it.fullEconomics.interfaces;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Collection;
import java.util.Scanner;
import java.util.Vector;
import ar.com.ford.it.fullEconomics.FullEconomicsPrs;
import ar.com.ford.it.fullEconomics.exception.FullEconomicsException;
import ar.com.ford.it.fullEconomics.interfaces.exception.FileNotFoundInDatabaseException;
import ar.com.ford.it.fullEconomics.interfaces.interfaz.InterfaceProccesFile;
import ar.com.ford.it.fullEconomics.logic.LogProcessLogic;
import ar.com.ford.it.fullEconomics.persistence.dto.Teesx02Fileconten;
import ar.com.ford.it.fullEconomics.persistence.dto.Teesx03Intflog;
import ar.com.ford.it.fullEconomics.struct.CounterStruct;
import cobolConversion.EbcdicString;
import cobolConversion.EbcdicTable;

public final class ReadFile {
    private ByteArrayInputStream contentArray;

    /**
     * @param aFileName
     * full name of an existing, readable file.
     * @param file
     * @throws FullEconomicsException
     */
    public ReadFile(Teesx02Fileconten fileContent,String processName) throws FileNotFoundInDatabaseException {
        
    	try 
    	{
    		contentArray = new ByteArrayInputStream(fileContent.getEesx02FconFileBlobO());
    	}catch (NullPointerException ne)
    	{
    		throw new FileNotFoundInDatabaseException("No se encontro archivo para el proceso " + processName);
    	}
    }

    /**
     * Procesa la linea leida segun la estrategia de cada archivo.
     * 
     * @param strategyRead
     * @param intflog
     * @param user
     * @throws FileNotFoundException
     * @throws FullEconomicsException
     * @throws FullEconomicsException
     */
    public final void processLineByLine(InterfaceProccesFile strategyRead,
                                        Teesx03Intflog intflog, String userId)
            throws FullEconomicsException {
        Scanner scanner = null;
        scanner = new Scanner(contentArray);
        LogProcessLogic logProcessLogic = new LogProcessLogic();
        CounterStruct counter = new CounterStruct();
        int countLine = 0;
        boolean trailerRead = false;
        int trailerRecordCount = 0;
        
        // BORRAR
        FileOutputStream fos;
        try {
           fos = new FileOutputStream("c:\\ee_file_blob");
       // END BORRAR - ver mas abajo el catch
        
        
        try {
            Collection data = new Vector<Object>();

            while (scanner.hasNext()) {
                String line = scanner.nextLine();
                
                // BORRAR
                try {
                   String strLineWrite = line + System.getProperty("line.separator"); 	
                fos.write(strLineWrite.getBytes());
                } catch (Exception e) {
                    System.out.println("Error grabando archivo a disco");
                }
                
                if (strategyRead.validateHeaderAndTrailer((Object) line)) {
                    strategyRead.processLine((Object) line, userId, data);
                } else {
                    // Comienzo o fin de archivo
                    if (countLine == 0 && line.trim().length() != 0) {
                        String descriptionPring = strategyRead
                                .getHeaderDescription((Object) line);
                        // Factorizar esta descripcion para que quede mas
                        // presentable.
                        logProcessLogic.insertLogIntfLevent(userId, intflog,
                                "M", "Property File Header" + descriptionPring,
                                0);
                    }
                    // Es el trailer valido la cantidad de registros que se
                    // procesaron.
                    if (countLine != 0) {
                        if (line.toString().length() != 1) {
                            String descriptionPrint = strategyRead
                                    .getTrailerDescription((Object) line);
                            logProcessLogic.insertLogIntfLevent(userId,
                                    intflog, "M", "Property File Trailer"
                                            + descriptionPrint, 0);
                            trailerRecordCount = strategyRead
                            .getRecordCount((Object) line);
                            trailerRead = true;
                        }
                    }
                }
                countLine++;
            }
            if (!trailerRead) {
                logProcessLogic.insertLogIntfLevent(userId, intflog, "E",
                        "No se encontro el trailer", countLine);
                counter.addError();
                throw new FullEconomicsException(new Exception(), FullEconomicsPrs.MessageErrors.Interface.NOTRAILER);
            } else if (!strategyRead.validateRecordCount(trailerRecordCount, countLine, data.size())) {
                logProcessLogic.insertLogIntfLevent(userId, intflog, "E",
                        "Cantidad de registros incorrecta. Se leyeron"
                                + data.size() + "registros, se declaro "
                                + trailerRecordCount + "registros", countLine);
                counter.addError();
                throw new FullEconomicsException(new Exception(),FullEconomicsPrs.MessageErrors.Interface.BADRECORCOUNT);
            } else {
                logProcessLogic.insertLogIntfLevent(userId, intflog, "M",
                        "Se leyo el archivo correctamente", countLine);
                /*CounterStruct insertCount = strategyRead.insertData(data, userId, intflog);
                counter = counter.add(insertCount);
                	COMENTADO PARA HACER DOWNLOAD DE ARCHIVOS
                */
                logProcessLogic.insertLogIntfLevent(userId, intflog, "M",
                        "Se actualizaron " + data.size() + "piezas", countLine);
            }
        } catch (FullEconomicsException e) {
            e.printStackTrace();
            throw e;
            
        } finally {
            // ensure the underlying stream is always closed
            logProcessLogic.insertLogIntfLevent(userId, intflog, "M",
                    "Proceso Finalizado, Errores: " + counter.getErrors() + " Advertencias: "
                            + counter.getWarnings() + " Completo: " + counter.getCount(), countLine);
            scanner.close();

        }
        
//      BORRAR ESTE BLOQUE Y EL CATCH
        try {
        	fos.close();
        	System.out.println(">>>>>>>>>> FIN GRABACION ARCHIVO <<<<<<<<<<<");
            } catch (Exception e) {
                System.out.println("Error grabando archivo a disco");
            }
        
        }
        catch (FileNotFoundException e) {
           System.out.println("Error grabando archivo a disco");
        }
    }

    public final void processLineByArray(InterfaceProccesFile strategyRead,
                                         Teesx03Intflog intflog, String userId)
            throws FullEconomicsException {
        BufferedInputStream myMvsFile = null;

        LogProcessLogic logProcessLogic = new LogProcessLogic();
        boolean trailerRead = false;
        int countLine = 0;
        int byteReads = 0;
        int trailerRecordCount = 0;
        byte myBufferRead[] = new byte[650];
        CounterStruct counter = new CounterStruct();
        try {
            myMvsFile = new BufferedInputStream(contentArray);
            // Leo la primera linea
            byteReads = myMvsFile.read(myBufferRead, 0, 650);
            Collection data = new Vector<Object>();
            while (byteReads != -1) {
                
            	// LSPARACI
            	System.out.println("+++LINE: " + countLine);
            	            	
//            	if (countLine==163)
//            		System.out.println("163 - AHORA!!!");
            	
                // Verifico si es el header o trailer del archivo
                if (strategyRead
                        .validateHeaderAndTrailer((Object) myBufferRead)) {

                    strategyRead.processLine((Object) myBufferRead, userId,
                            data);
                    
                } else {
                    // Comienzo o fin de archivo
                    if (countLine == 0) {
                        String descriptionPring = strategyRead
                                .getHeaderDescription((Object) myBufferRead);
                        // Factorizar esta descripcion

                        logProcessLogic.insertLogIntfLevent(userId, intflog,
                                "M", "Property File Header" + descriptionPring,
                                0);

                    } else {
                        String descriptionPrint = strategyRead
                                .getTrailerDescription((Object) myBufferRead);

                        trailerRecordCount = strategyRead
                                .getRecordCount((Object) myBufferRead);
                        logProcessLogic.insertLogIntfLevent(userId, intflog,
                                "M",
                                "Property File Trailer" + descriptionPrint, 0);
                        trailerRead = true;
                    }
                }
                byteReads = myMvsFile.read(myBufferRead, 0, 650);
                countLine++;
            }
            if (!trailerRead) {
                logProcessLogic.insertLogIntfLevent(userId, intflog, "E",
                        "Error al leer el archivo almacenado", countLine);
                counter.addError();
                throw new FullEconomicsException(new Exception(), FullEconomicsPrs.MessageErrors.Interface.NOTRAILER);
            } else if (!strategyRead.validateRecordCount(trailerRecordCount, countLine, data.size())) {
                logProcessLogic.insertLogIntfLevent(userId, intflog, "E",
                        "Cantidad de registros incorrecta. Se leyeron "
                                + data.size() + " registros, se declaro "
                                + trailerRecordCount + " registros", countLine);
                counter.addError();
                throw new FullEconomicsException(new Exception(),FullEconomicsPrs.MessageErrors.Interface.BADRECORCOUNT);
            } else {
                logProcessLogic.insertLogIntfLevent(userId, intflog, "M",
                        "Se leyo el archivo correctamente", countLine);
                CounterStruct insertCounter = strategyRead.insertData(data, userId, intflog);
                counter = counter.add(insertCounter);
                logProcessLogic.insertLogIntfLevent(userId, intflog, "M",
                        "Se actualizaron " + data.size() + " piezas", countLine);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            throw new FullEconomicsException(e);
        } catch (IOException e) {
            e.printStackTrace();
            throw new FullEconomicsException(e);
        } finally {
            logProcessLogic.insertLogIntfLevent(userId, intflog, "M",
                    "Proceso Finalizado, Errores: " + counter.getErrors() + " Advertencias: "
                            + counter.getWarnings() + " Completo: " + counter.getCount(), countLine);
            try {
                myMvsFile.close();
            } catch (IOException e) {
                // TODO Error al cerrar el archivo
                e.printStackTrace();
            }
        }
    }

    private boolean isTrailer(byte[] myBufferRead) {
        EbcdicTable ebcdicTable = new EbcdicTable();
        ebcdicTable.set_pageCode(EbcdicTable.ASCII_USA_00437);
        EbcdicString ebcdicString = new EbcdicString(ebcdicTable, myBufferRead);
        if (ebcdicString.toString().toString().trim().contains("TRAILER")) {
            return true;
        }
        return false;
    }

    private boolean isHeader(byte[] myBufferRead) {
        EbcdicTable ebcdicTable = new EbcdicTable();
        ebcdicTable.set_pageCode(EbcdicTable.ASCII_USA_00437);
        EbcdicString ebcdicString = new EbcdicString(ebcdicTable, myBufferRead);
        if (ebcdicString.toString().toString().trim().contains("00000001")) {
            return true;
        }
        return false;
    }

    public ByteArrayInputStream getContentArray() {
        return contentArray;
    }

    public void setContentArray(ByteArrayInputStream contentArray) {
        this.contentArray = contentArray;
    }
}
